import React, { useState, useEffect } from 'react';
import { ethers } from 'ethers';
import { QRCodeSVG } from 'qrcode.react'; // 使用命名导出 SVG 组件
import './App.css';

const contractABI = [
  "function rate() view returns (uint256)",
  "function owner() view returns (address)",
  "function balanceOf(address) view returns (uint256)",
  "function withdrawETH()",
  "function setRate(uint256 _newRate)",
  "function name() view returns (string)",
  "function symbol() view returns (string)",
  "function decimals() view returns (uint8)",
  "function totalSupply() view returns (uint256)",
  "receive() external payable"
] as const;

const contractAddress = "0x3e0e21fD807E961845Eb78851015b2b27B3b4147";

interface ContractBalance {
  tokens: string;
  eth: string;
}

const App: React.FC = () => {
  const [provider, setProvider] = useState<ethers.BrowserProvider | null>(null);
  const [signer, setSigner] = useState<ethers.Signer | null>(null);
  const [contract, setContract] = useState<ethers.Contract | null>(null);
  const [account, setAccount] = useState<string | null>(null);
  const [rate, setRate] = useState<string | null>(null);
  const [owner, setOwner] = useState<string | null>(null);
  const [contractBalance, setContractBalance] = useState<ContractBalance | null>(null);
  const [userBalance, setUserBalance] = useState<string | null>(null);
  const [userEthBalance, setUserEthBalance] = useState<string | null>(null);
  const [tokenName, setTokenName] = useState<string | null>(null);
  const [tokenSymbol, setTokenSymbol] = useState<string | null>(null);
  const [totalSupply, setTotalSupply] = useState<string | null>(null);
  const [ethAmount, setEthAmount] = useState<string>('');
  const [tokenAmount, setTokenAmount] = useState<string>('0');
  const [newRate, setNewRate] = useState<string>('');
  const [rechargeAmount, setRechargeAmount] = useState<string>('');
  const [qrCodeValue, setQrCodeValue] = useState<string | null>(null);
  const [loading, setLoading] = useState<boolean>(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const init = async () => {
      try {
        if (typeof window.ethereum === 'undefined') {
          throw new Error('请安装 MetaMask!');
        }
        const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }) as string[];
        const web3Provider = new ethers.BrowserProvider(window.ethereum);
        const signer = await web3Provider.getSigner();
        const contractInstance = new ethers.Contract(contractAddress, contractABI, signer);

        setProvider(web3Provider);
        setSigner(signer);
        setContract(contractInstance);
        setAccount(accounts[0]);

        window.ethereum.on('accountsChanged', (newAccounts: string[]) => setAccount(newAccounts[0]));
        window.ethereum.on('chainChanged', () => window.location.reload());

        await fetchData(contractInstance, web3Provider, accounts[0]);
      } catch (err: any) {
        setError(err.message);
      }
    };
    init();
  }, []);

  const fetchData = async (
    contractInstance: ethers.Contract,
    providerInstance: ethers.BrowserProvider,
    userAccount: string
  ) => {
    try {
      const rateValue = await contractInstance.rate();
      const ownerAddress = await contractInstance.owner();
      const contractTokenBalance = await contractInstance.balanceOf(contractAddress);
      const userTokenBalance = await contractInstance.balanceOf(userAccount);
      const userEth = await providerInstance.getBalance(userAccount);
      const ethBalance = await providerInstance.getBalance(contractAddress);
      const name = await contractInstance.name();
      const symbol = await contractInstance.symbol();
      const supply = await contractInstance.totalSupply();

      setRate(ethers.formatUnits(rateValue, 18));
      setOwner(ownerAddress);
      setContractBalance({
        tokens: ethers.formatEther(contractTokenBalance),
        eth: ethers.formatEther(ethBalance)
      });
      setUserBalance(ethers.formatEther(userTokenBalance));
      setUserEthBalance(ethers.formatEther(userEth));
      setTokenName(name);
      setTokenSymbol(symbol);
      setTotalSupply(ethers.formatEther(supply));
    } catch (err: any) {
      setError('获取数据失败: ' + err.message);
    }
  };

  useEffect(() => {
    if (ethAmount && rate) {
      const eth = parseFloat(ethAmount);
      const rateNum = parseFloat(rate);
      if (!isNaN(eth) && !isNaN(rateNum)) {
        setTokenAmount((eth * rateNum).toFixed(2));
      } else {
        setTokenAmount('0');
      }
    } else {
      setTokenAmount('0');
    }
  }, [ethAmount, rate]);

  const buyTokens = async () => {
    if (!contract || !signer || !ethAmount) return;
    setLoading(true);
    try {
      const tx = await signer.sendTransaction({
        to: contractAddress,
        value: ethers.parseEther(ethAmount)
      });
      await tx.wait();
      if (contract && provider) {
        await fetchData(contract, provider, account!);
      }
      setEthAmount('');
      setError(null);
    } catch (err: any) {
      setError('购买失败: ' + err.message);
    }
    setLoading(false);
  };

  const withdrawETH = async () => {
    if (!contract) return;
    setLoading(true);
    try {
      const tx = await contract.withdrawETH();
      await tx.wait();
      if (contract && provider) {
        await fetchData(contract, provider, account!);
      }
      setError(null);
    } catch (err: any) {
      setError('提取失败: ' + err.message);
    }
    setLoading(false);
  };

  const updateRate = async () => {
    if (!contract || !newRate) return;
    setLoading(true);
    try {
      const tx = await contract.setRate(newRate);
      await tx.wait();
      if (contract && provider) {
        await fetchData(contract, provider, account!);
      }
      setNewRate('');
      setError(null);
    } catch (err: any) {
      setError('修改比例失败: ' + err.message);
    }
    setLoading(false);
  };

  const generateRechargeQR = () => {
    if (!rechargeAmount) {
      setError('请输入充值金额');
      return;
    }
    const amountInWei = ethers.parseEther(rechargeAmount).toString();
    const qrValue = `ethereum:${contractAddress}?value=${amountInWei}`;
    setQrCodeValue(qrValue);
    setError(null);
  };

  return (
    <div className="web3-wallet">
      <header className="wallet-header">
        <h1>Web3 钱包</h1>
        <div className="account-info">
          <span>{account || '未连接'}</span>
          <button
            className="refresh-btn"
            onClick={() => contract && provider && fetchData(contract, provider, account!)}
            disabled={loading}
          >
            ↻
          </button>
        </div>
      </header>

      {error && <div className="error-message">{error}</div>}

      <section className="balance-section">
        <div className="balance-card">
          <h2>资产</h2>
          <div className="balance-item">
            <span>{tokenSymbol || 'TOKEN'}</span>
            <span>{userBalance || '0.0'}</span>
          </div>
          <div className="balance-item">
            <span>ETH</span>
            <span>{userEthBalance || '0.0'}</span>
          </div>
        </div>

        <div className="info-card">
          <h2>合约信息</h2>
          <div className="info-item">
            <span>代币名称</span>
            <span>{tokenName || '加载中...'}</span>
          </div>
          <div className="info-item">
            <span>代币符号</span>
            <span>{tokenSymbol || '加载中...'}</span>
          </div>
          <div className="info-item">
            <span>兑换比例</span>
            <span>1 ETH = {rate || '加载中...'} {tokenSymbol}</span>
          </div>
          <div className="info-item">
            <span>合约 ETH</span>
            <span>{contractBalance?.eth || '0.0'} ETH</span>
          </div>
        </div>

        <div className="action-card">
          <h3>生成充值二维码</h3>
          <div className="input-group">
            <input
              type="number"
              value={rechargeAmount}
              onChange={(e) => setRechargeAmount(e.target.value)}
              placeholder="输入充值 ETH 数量"
              disabled={loading}
            />
            <span className="unit">ETH</span>
          </div>
          <button onClick={generateRechargeQR} disabled={loading || !rechargeAmount}>
            {loading ? '处理中...' : '生成二维码'}
          </button>
          {qrCodeValue && (
            <div className="qr-code">
              <QRCodeSVG value={qrCodeValue} size={128} bgColor="#1e1e2f" fgColor="#ffffff" />
            </div>
          )}
        </div>
      </section>

      <section className="action-section">
        <div className="action-card">
          <h3>兑换代币</h3>
          <div className="input-group">
            <input
              type="number"
              value={ethAmount}
              onChange={(e) => setEthAmount(e.target.value)}
              placeholder="输入 ETH 数量"
              disabled={loading}
            />
            <span className="unit">ETH</span>
          </div>
          <div className="convert-info">
            可获得: {tokenAmount} {tokenSymbol}
          </div>
          <button onClick={buyTokens} disabled={loading || !ethAmount}>
            {loading ? '处理中...' : '兑换'}
          </button>
        </div>

        {account && owner && account.toLowerCase() === owner.toLowerCase() && (
          <div className="owner-actions">
            <div className="action-card">
              <h3>提取 ETH</h3>
              <p>可用: {contractBalance?.eth || '0.0'} ETH</p>
              <button onClick={withdrawETH} disabled={loading}>
                {loading ? '处理中...' : '提取'}
              </button>
            </div>
            <div className="action-card">
              <h3>调整比例</h3>
              <div className="input-group">
                <input
                  type="number"
                  value={newRate}
                  onChange={(e) => setNewRate(e.target.value)}
                  placeholder="输入新比例"
                  disabled={loading}
                />
                <span className="unit">{tokenSymbol}</span>
              </div>
              <button onClick={updateRate} disabled={loading || !newRate}>
                {loading ? '处理中...' : '调整'}
              </button>
            </div>
          </div>
        )}
      </section>

      <footer className="wallet-footer">
        <p>合约地址: {contractAddress}</p>
      </footer>
    </div>
  );
};

export default App;